package geometry;

import constraint.Variable;
import constraint.VariableType;
import foundationgeom.AxialFrame;
import foundationgeom.Axis;
import foundationgeom.CartesianCoordinateSystem;
import foundationgeom.CoordinateSystem;
import foundationgeom.EulerAngles;
import foundationgeom.GeomFactory;
import foundationgeom.Transformation;
import foundationgeom.Vector;

public class CoordSys {
    private Variable x;
    private Variable y;
    private Variable z;
    private CoordSys parent;
    private CoordinateSystem cs;
    
    public CoordSys(CoordSys parent, Geometry geometry) {
        cs = new CartesianCoordinateSystem(parent.cs);
        x = new Variable(0, VariableType.X_POS, geometry, null);
        y = new Variable(0, VariableType.Y_POS, geometry, null);
        z = new Variable(0, VariableType.Z_POS, geometry, null);
        this.parent = parent;
    }

    public Transformation getTransformationTo(CoordSys coordSys) {
        return cs.getTransformationTo(coordSys.cs);
    }
    
    public String toString() {
        return cs.toString();
    }
    
    private CoordSys() {
    }

    public void setOriginDisplacement(Vector disp) {
        cs.setOriginDisplacement(disp);
        setVariables();
    }

    private void setVariables() {
        Vector disp = cs.getOriginDisplacement();
        x.setValue(disp.getX());
        y.setValue(disp.getY());
        z.setValue(disp.getZ());
    }

    public void setOrientation(EulerAngles orientation) {
        cs.setOrientation(orientation);
        setVariables();
    }

    public Vector difference(CoordSys cs2) {
        return this.cs.getOriginDisplacement().subtract(cs2.cs.getOriginDisplacement());
    }

    public void translate(Vector translate) {
        this.cs.translate(translate);
        setVariables();
    }

    public Vector getOriginDisplacement() {
        return cs.getOriginDisplacement();
    }

    public EulerAngles getEulerAngles() {
        return cs.getEulerAngles();
    }

    public CoordSys getParent() {
        return parent;
    }

    public AxialFrame getAxialFrame() {
        return cs.getAxialFrame();
    }

    public boolean equal(CoordSys cs2) {
        return this.cs.equal(cs2.cs);
    }

    public static CoordSys createRootCoordinateSystem() {
        CoordSys cs = new CoordSys();
        cs.cs = GeomFactory.getFactory().createRootCoordinateSystem();
        cs.x = new Variable(0, VariableType.X_POS, null, null);
        cs.y = new Variable(0, VariableType.Y_POS, null, null);
        cs.z = new Variable(0, VariableType.Z_POS, null, null);        
        return cs;
    }

    public void setOrientation(AxialFrame axialFrame) {
        this.cs.setOrientation(axialFrame);
        setVariables();
    }

    public void rotate(Axis axis, double value) {
        cs.rotate(axis, value);
        setVariables();
    }

    public void changeParentTo(CoordSys coordSys) {
        parent=coordSys;
        cs.changeParentTo(coordSys.cs);
    }

    public Variable getVariable(VariableType type) {
        if (type == VariableType.X_POS) {
            return x;
        } else if (type == VariableType.Y_POS) {
            return y;
        } else if (type == VariableType.Z_POS) {
            return z;
        }
        return null;
    }

    public Variable[] getVariables() {
        return new Variable[]{x,y,z};
    }
}
